using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Web.Razor;

namespace Noria.Parnters.Parker
{
    class SimpleRazorEngine
    {
        public static string Parse(string template, dynamic viewBag, bool minify = true)
        {
            var host = new RazorEngineHost(new CSharpRazorCodeLanguage()) { DefaultBaseClass = typeof(Template).FullName };
            var engine = new RazorTemplateEngine(host);
            var results = engine.GenerateCode(new StringReader(template));
            if (results.Success)
            {
                var provider = new CSharpCodeProvider();
                var option = new CompilerParameters()
                                 {
                                     GenerateInMemory = true,
                                     GenerateExecutable = false,
                                     IncludeDebugInformation = false,
                                     CompilerOptions = "/target:library /optimize",
                                 };
                option.ReferencedAssemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic).Select(p => p.Location).ToArray());
                var r = provider.CompileAssemblyFromDom(option, results.GeneratedCode);

                if (!r.Errors.HasErrors)
                {
                    var asm = r.CompiledAssembly;
                    var razor = asm.GetType("Razor.__CompiledTemplate"); // this is the default name that Razor generates
                    var instance = Activator.CreateInstance(razor) as ITemplate;

                    try
                    {
                        instance.ViewBag = viewBag;
                        instance.Execute();
                        return instance.Result.Replace("<a>", "").Replace("</a>", "");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        throw new ApplicationException("RazorExecutionError", e);
                    }
                }
                else
                {
                    foreach (CompilerError err in r.Errors)
                    {
                        Console.WriteLine(" error: {0}", err.ErrorText);
                    }
                    throw new ApplicationException("CompilerError");
                }
            }
            else
            {
                Console.WriteLine("Failed to generate code, {0}", results.ParserErrors.First().Message);
                throw new ApplicationException("GenerateCodeError");
            }
        }
    }
}